package com.tarena.lbs.attach.service.impl;

import com.tarena.lbs.attach.dao.repository.AttachRepository;
import com.tarena.lbs.attach.enums.AttachResultEnum;
import com.tarena.lbs.attach.enums.FileStatusEnum;
import com.tarena.lbs.attach.enums.FileTypeEnum;
import com.tarena.lbs.attach.pojo.dto.AttachDTO;
import com.tarena.lbs.attach.pojo.dto.AttachQrDTO;
import com.tarena.lbs.attach.pojo.param.AttachQRParam;
import com.tarena.lbs.attach.pojo.param.PicUpdateParam;
import com.tarena.lbs.attach.pojo.po.AttachPO;
import com.tarena.lbs.attach.pojo.query.AttachQuery;
import com.tarena.lbs.attach.pojo.vo.FileVO;
import com.tarena.lbs.attach.service.AttachService;
import com.tarena.lbs.attach.utils.FileUtil;
import com.tarena.lbs.attach.utils.QRCodeUtil;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.common.principle.UserPrinciple;
import com.tarena.lbs.common.utils.AuthenticationContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AttachServiceImpl implements AttachService {

    @Autowired
    private AttachRepository attachRepository;


    @Value("${image_path}")
    private String imagePath;
    @Value("${url}")
    private String url;


    @Override
    public FileVO upload(MultipartFile file) throws Exception {

        // 1. 校验文件非空
        if (file == null || file.isEmpty()) {
            throw new BusinessException("-2","上传文件不能为空");
        }

        // 2. 获取当前登录用户信息（从上下文获取）
        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
        if (userPrinciple == null || userPrinciple.getId() == null) {
            throw new BusinessException("-2","请先登录");
        }
        // 处理用户ID（Integer转Long）
        Long userId = userPrinciple.getId() != null ? userPrinciple.getId().longValue() : null;

        // 3. 生成文件唯一标识（UUID）
        String fileUuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();

        // 4. 保存文件到本地（使用原FileUtil工具类）
        String fileName = FileUtil.makeTempFile(file, imagePath, fileUuid);

        // 5. 构建AttachPO对象并赋值
        AttachPO attachPO = new AttachPO();
        attachPO.setFileUuid(fileUuid);
        attachPO.setClientFileName(file.getOriginalFilename());
        attachPO.setDownloadTimes(0);
        attachPO.setContentLength(file.getSize());

        // 文件类型转换（结合枚举）
        FileTypeEnum fileType = FileTypeEnum.fromContentType(file.getContentType());
        attachPO.setContentType(fileType.getType());

        attachPO.setIsCover(0); // 默认非封面

        // 图片宽高解析（仅图片类型）
        if (FileTypeEnum.PICTURE.equals(fileType)) {
            BufferedImage image = ImageIO.read(file.getInputStream());
            attachPO.setWidth(image.getWidth());
            attachPO.setHeight(image.getHeight());
        } else {
            attachPO.setWidth(null);
            attachPO.setHeight(null);
        }

        attachPO.setBusinessType(0); // 初始未绑定业务
        attachPO.setBusinessId(0);
        attachPO.setStatus(FileStatusEnum.ENABLE.getType()); // 状态为有效
        attachPO.setRemark("web接口上传");

        // 操作人信息
        attachPO.setCreateUserId(userId);
        attachPO.setGmtCreate(System.currentTimeMillis());
        attachPO.setCreateUserName(userPrinciple.getNickname());
        attachPO.setModifiedUserId(userId);
        attachPO.setGmtModified(System.currentTimeMillis());
        attachPO.setModifiedUserName(userPrinciple.getNickname());

        // 6. 保存到数据库
        attachRepository.saveFile(attachPO);

        // 7. 构建并返回FileVO
        FileVO fileVO = new FileVO();
        fileVO.setFileUuid(fileUuid); // 文件唯一标识
        fileVO.setUrl(url + fileName); // 完整访问URL
        return fileVO;
    }

    @Override
    public List<AttachDTO> getAttachInfo(AttachQuery attachQuery) {
        if (attachQuery == null || attachQuery.getBusinessType() == null || attachQuery.getBusinessId() == null) {
            log.warn("查询附件信息参数不完整: {}", attachQuery);
            return Collections.emptyList();
        }

        try {
            List<AttachPO> attachPOs = attachRepository.queryAttachInfo(attachQuery);
            return attachPOs.stream()
                    .map(this::convertToDTO)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("查询附件信息失败", e);
            return Collections.emptyList();
        }
    }

    @Override
    public boolean batchUpdateBusiness(List<PicUpdateParam> picParams) {
        // 1. 参数校验
        if (CollectionUtils.isEmpty(picParams)) {
            log.warn("批量更新业务参数为空");
            return false;
        }

        // 2. 获取当前登录用户
        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
        if (userPrinciple == null || userPrinciple.getId() == null) {
            log.error("批量更新失败：未获取到登录用户信息");
            return false;
        }
        Long modifiedUserId = userPrinciple.getId().longValue();
        String modifiedUserName = userPrinciple.getNickname();

        // 3. 循环更新
        for (PicUpdateParam param : picParams) {
            if (param.getId() == null || param.getBusinessType() == null || param.getBusinessId() == null) {
                log.warn("跳过无效的更新参数: {}", param);
                continue;
            }
            AttachPO attachPO = new AttachPO();
            attachPO.setId(param.getId());
            attachPO.setBusinessType(param.getBusinessType());
            attachPO.setBusinessId(param.getBusinessId());
            attachPO.setModifiedUserId(modifiedUserId);
            attachPO.setModifiedUserName(modifiedUserName);
            attachPO.setGmtModified(System.currentTimeMillis());
            attachRepository.updateById(attachPO); // 需在AttachRepository中定义updateById方法
        }
        return true;
    }

    @Override
    public boolean deleteAttachInfo(String fileUuid) {
        if (StringUtils.isBlank(fileUuid)) {
            log.warn("删除附件参数为空");
            return false;
        }

        try {
            return attachRepository.deleteAttachInfo(fileUuid);
        } catch (Exception e) {
            log.error("删除附件信息失败，fileUuid: {}", fileUuid, e);
            return false;
        }
    }

    @Override
    public AttachQrDTO generateQrCode(AttachQRParam attachQRParam) throws BusinessException {
        // 1. 获取当前用户
        UserPrinciple userPrinciple = getCurrentUser();
        Long userId = userPrinciple.getId().longValue();

        // 2. 参数校验
        if (attachQRParam == null || StringUtils.isBlank(attachQRParam.getContent())
                || attachQRParam.getBusinessType() == null || attachQRParam.getBusinessId() == null) {
            log.error("生成二维码参数错误: {}", attachQRParam);
            throw new BusinessException(AttachResultEnum.BIND_ERROR.getCode(), "二维码参数不完整");
        }

        // 3. 生成文件标识和路径
        String fileUuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
        String fileName = fileUuid + ".png";
        File saveDir = new File(imagePath);

        // 4. 生成二维码文件
        try {
            QRCodeUtil.createCodeToFile(attachQRParam.getContent(), saveDir, fileName);
        } catch (Exception e) {
            log.error("生成二维码文件失败", e);
            throw new BusinessException(AttachResultEnum.SYSTEM_ERROR.getCode(), "生成二维码失败");
        }

        // 5. 构建并保存PO
        AttachPO attachPO = new AttachPO();
        attachPO.setFileUuid(fileUuid);
        attachPO.setClientFileName(fileName);
        attachPO.setContentLength(new File(saveDir, fileName).length());
        attachPO.setContentType(FileTypeEnum.PICTURE.getType());
        attachPO.setBusinessType(attachQRParam.getBusinessType());
        attachPO.setBusinessId(attachQRParam.getBusinessId());
        attachPO.setStatus(FileStatusEnum.ENABLE.getType());
        attachPO.setGmtCreate(System.currentTimeMillis());
        attachPO.setCreateUserId(userId);
        attachPO.setCreateUserName(userPrinciple.getNickname());
        attachPO.setModifiedUserId(userId);
        attachPO.setGmtModified(System.currentTimeMillis());
        attachPO.setModifiedUserName(userPrinciple.getNickname());
        attachPO.setRemark("自动生成的二维码，内容: " + attachQRParam.getContent());

        attachRepository.saveFile(attachPO);

        // 6. 转换为DTO返回
        AttachQrDTO result = new AttachQrDTO();
        result.setId(attachPO.getId());
        result.setFileUuid(fileUuid);
        result.setUrl(url + fileName);
        return result;
    }

    @Override
    public List<AttachDTO> bindPic(List<PicUpdateParam> picParams) throws BusinessException {
        // 1. 校验参数非空
        if (CollectionUtils.isEmpty(picParams)) {
            log.error("批量绑定图片失败：参数列表为空");
            throw new BusinessException(AttachResultEnum.BIND_ERROR.getCode(), "绑定参数列表不能为空");
        }

        // 2. 获取当前登录用户
        UserPrinciple userPrinciple = getCurrentUser();
        Long userId = userPrinciple.getId().longValue();
        String userName = userPrinciple.getNickname();

        // 3. 批量处理每个绑定参数
        List<AttachDTO> resultList = new ArrayList<>();
        for (PicUpdateParam param : picParams) {
            try {
                // 3.1 校验单个参数合法性

                validateBindParam(param);

                // 3.2 查询原始图片（根据fileUuid）
                AttachPO originalPO = attachRepository.getByFileUuid(param.getFileUuid());
                if (originalPO == null) {
                    log.warn("跳过无效绑定：原始图片不存在，fileUuid: {}", param.getFileUuid());
                    continue; // 跳过当前无效参数，继续处理其他参数
                }

                // 3.3 生成新文件标识和名称（保持原文件后缀）
                String newFileUuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
                String newFileName = generateNewFileName(originalPO.getClientFileName(), newFileUuid);

                // 3.4 复制原始文件到新路径
                File originalFile = new File(imagePath, originalPO.getClientFileName());
                File newFile = new File(imagePath, newFileName);
                validateAndCopyFile(originalFile, newFile);

                // 3.5 构建新的附件PO（绑定记录）
                AttachPO newAttachPO = buildNewAttachPO(originalPO, param, newFileUuid, newFileName, newFile, userId, userName);
                attachRepository.saveFile(newAttachPO);
                log.info("图片绑定成功，新UUID: {}，绑定业务: {}:{}",
                        newFileUuid, param.getBusinessType(), param.getBusinessId());

                // 3.6 转换为DTO并添加到结果列表
                AttachDTO resultDTO = new AttachDTO();
                BeanUtils.copyProperties(newAttachPO, resultDTO);
                resultList.add(resultDTO);

            } catch (BusinessException e) {
                // 业务异常：记录日志，继续处理下一个参数
                log.error("处理绑定参数失败: {}", param, e);
                continue;
            } catch (Exception e) {
                // 系统异常：记录日志，继续处理下一个参数
                log.error("图片绑定系统异常，参数: {}", param, e);
                continue;
            }
        }

        // 4. 校验是否有成功绑定的记录
        if (CollectionUtils.isEmpty(resultList)) {
            log.warn("所有绑定参数均处理失败，参数列表: {}", picParams);
            throw new BusinessException(AttachResultEnum.BIND_ERROR.getCode(), "所有图片绑定均失败，请检查参数");
        }

        return resultList;
    }


    // 转换PO为DTO
    private AttachDTO convertToDTO(AttachPO po) {
        AttachDTO dto = new AttachDTO();
        BeanUtils.copyProperties(po, dto);
        dto.setContentLength(Math.toIntExact(po.getContentLength())); // 处理Long转Integer
        return dto;
    }

    // 获取当前登录用户（封装通用逻辑）
    private UserPrinciple getCurrentUser() throws BusinessException {
        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
        if (userPrinciple == null || userPrinciple.getId() == null) {
            log.error("未获取到登录用户信息");
            throw new BusinessException("-1", "请先登录");
        }
        return userPrinciple;
    }

    // 校验绑定参数
    private void validateBindParam(PicUpdateParam param) throws BusinessException {
        if (param == null) {
            throw new BusinessException(AttachResultEnum.BIND_ERROR.getCode(), "绑定参数不能为空");
        }
        if (StringUtils.isBlank(param.getFileUuid())) {
            throw new BusinessException(AttachResultEnum.BIND_ERROR.getCode(), "文件唯一标识（fileUuid）不能为空");
        }
        if (param.getBusinessType() == null) {
            throw new BusinessException(AttachResultEnum.BIND_ERROR.getCode(), "业务类型（businessType）不能为空");
        }
        if (param.getBusinessId() == null) {
            throw new BusinessException(AttachResultEnum.BIND_ERROR.getCode(), "业务ID（businessId）不能为空");
        }
    }

    // 生成新文件名（保留原始后缀）
    private String generateNewFileName(String originalFileName, String newFileUuid) {
        String fileSuffix = "";
        int dotIndex = originalFileName.lastIndexOf(".");
        if (dotIndex > 0) {
            fileSuffix = originalFileName.substring(dotIndex);
        }
        return newFileUuid + fileSuffix;
    }

    // 校验并复制文件
    private void validateAndCopyFile(File originalFile, File newFile) throws Exception {
        if (!originalFile.exists() || !originalFile.isFile()) {
            throw new BusinessException("-2", "原始文件不存在");
        }
        FileUtil.copyFile(originalFile, newFile); // 假设工具类会抛出异常
    }

    // 构建新的附件PO
    private AttachPO buildNewAttachPO(AttachPO originalPO, PicUpdateParam param,
                                      String newFileUuid, String newFileName, File newFile,
                                      Long userId, String userName) {
        AttachPO newPO = new AttachPO();
        newPO.setFileUuid(newFileUuid);
        newPO.setClientFileName(newFileName);
        newPO.setContentLength(newFile.length());
        newPO.setContentType(originalPO.getContentType());
        newPO.setIsCover(originalPO.getIsCover());
        newPO.setWidth(originalPO.getWidth());
        newPO.setHeight(originalPO.getHeight());
        newPO.setBusinessType(param.getBusinessType());
        newPO.setBusinessId(param.getBusinessId());
        newPO.setStatus(FileStatusEnum.ENABLE.getType());
        newPO.setCreateUserId(userId);
        newPO.setCreateUserName(userName);
        newPO.setGmtCreate(System.currentTimeMillis());
        newPO.setModifiedUserId(userId);
        newPO.setModifiedUserName(userName);
        newPO.setGmtModified(System.currentTimeMillis());
        newPO.setRemark("绑定自原始文件UUID：" + originalPO.getFileUuid());
        return newPO;
    }

}
